#pragma once

#include <iostream>
#include <string>
#include <sys/select.h>
#include "Sock.hpp"
#include "Log.hpp"
#include <cstring>

const static int gport = 8888;

class SelectServer
{
public:
    SelectServer(uint16_t port = gport) : port_(port)
    {
    }
    void InitServer()
    {
        listensock_.Socket();
        listensock_.Bind(port_);
        listensock_.Listen();
    }
    void HandlerEvent(fd_set &rfds)
    {
        if(FD_ISSET(listensock_.Fd(),&rfds))//判断这个sock在不在文件描述符集里
        {
            std::cout<<"有一个新链接到来了"<<std::endl;
            //这里再进行Accept会不会被阻塞？不会，因为我们已经检测到对应的listensock_已经有事件了

        }
    }
    void Start()
    {
        // 1、这里我们能够直接获取新的链接吗？
        // 2、最开始的时候，我们的服务器是没有太多的sock的，甚至只有一个sock，listensock
        // 3、在网络当中，新连接到来被当做读事件就绪，新连接来了，文件描述符才能越来越多
        //  listensock_.Accept();不能，要把新的sock添加到select中
        // demo0版
        // struct timeval timeout = {2, 0};
        fd_set rfds;
        FD_ZERO(&rfds);                  // 初始化
        FD_SET(listensock_.Fd(), &rfds); // 把listensock_读取到了文件描述符集里
        while (true)
        {
            // struct timeval timeout = {2, 0};//每次对这个时间都要做重置
            // int n = select(listensock_.Fd() + 1, &rfds, nullptr, nullptr, &timeout);//对struct timeval一般设为null，方便测试，阻塞等待
            int n = select(listensock_.Fd() + 1, &rfds, nullptr, nullptr, nullptr);
            switch (n)
            {
            case 0:
                logMessage(Debug, "timeout, %d: %s", errno, strerror(errno));
                break;
            case -1:
                logMessage(Warning, "%d: %s", errno, strerror(errno));
                break;
            default:
                // 成功了
                logMessage(Debug, "有一个就绪事件发生了: %d",n);
                HandlerEvent(rfds);
                break;
            }
            sleep(1);
        }
    }
    ~SelectServer()
    {
        listensock_.Close();
    }

private:
    uint16_t port_;
    Sock listensock_;
};